<?php
/**
 *
 * @version : 1.0
 * @since June-2008
 * @package lib
 * @subpackage data
 * @todo: process format XML file
*/
class CXml
{
	public $doc;
	/**
	 * Khởi tạo
	 *
	 * @param string $root
	 * @param mixed $data
	 */
	function __construct($root = false, $data = false)
	{
		$this->doc = new DOMDocument('1.0', 'utf-8');
		$this->doc->preserveWhiteSpace = false;
		$this->doc->formatOutput = true;
		if($root)
		{
			if(preg_match('/[^\w]/',$root))
			{
				if(preg_match('/[\<\>]/',$root))
				{
					$this->doc->loadXML($root);
				}
				else
				{
					$this->load($root);
				}
			}
			else
			{
				$element = $this->doc->createElement($root);
				$this->doc->appendChild($element);
			}
		}
	}
	/**
	 * Load dữ liệu từ file XML
	 *
	 * @param string $file_name
	 * @return DOM DOC
	 */
	function &load($file_name)
	{
		if(CFile::exists($file_name))
		{
			$this->doc->load($file_name);
		}
		return $this;
	}
	/**
	 * Lưu file XML
	 *
	 * @param string $file_name
	 * @return DOM DOC
	 */
	function &save($file_name)
	{
		if(strpos($file_name, 'ftp://') !== false)
		{
			CFile::ftp_fput(str_replace(FTP_PREFIX,'',$file_name), $this->doc->saveXML());
		}
		else
		{
			$this->doc->save($file_name);
		}
		return $this;
	}
	/**
	 * Lưu dữ liệu XML
	 *
	 * @return bool
	 */
	function code()
	{
		return $this->doc->saveXML();
	}

	/**
	 * Encode values for node
	 *
	 * @param mixed $data
	 * @param Object Node $node
	 * @return  Object Node
	 */
	function &encode($data, $node = false)
	{
		if(!$node)
		{
			$node = $this->doc->documentElement;
		}
		foreach($data as $key => $value)
		{
			// Recursive Algorithm
			if(is_array($value))
			{
				if(is_int($key))
				{
					if($node->nodeName[strlen($node->nodeName)-1] == 's')
					{
						$key = substr($node->nodeName, 0, strlen($node->nodeName)-1);
					}
					else
					{
						$key = $node->nodeName;
					}
				}
				$this->encode($value, $node->appendChild($this->doc->createElement($key)));
			}
			else
			{
				if(strlen($value)>255 or preg_match('/[^a-zA-Z0-9\s-@\._]/',$value))
				{
					$elem = $this->doc->createElement($key);
					$elem->appendChild($this->doc->createCDATASection($value));
					$node->appendChild($elem);
				}
				else
				{
					$node->appendChild($this->doc->createElement($key, $value));
				}
			}
		}
		return $node;
	}


	/**
	 * Tạo một node
	 *
	 * @param string $table
	 * @param mixed $values
	 * @return  Node Object
	 */

	function create_element($name, $values)
	{
		if(is_string($values))
		{
			return $this->doc->createElement($name, $values);
		}
		else
		{
			$node = $this->doc->createElement($name);
			$this->encode($values, $node);
			return $node;
		}
	}

	/**
	 * Lấy dữ liệu một node dạng array
	 *
	 * @param Node Object $node
	 * @return array
	 */
	function decode($node = false)
	{
		if(!$node)
		{
			$node = $this->doc->documentElement;
		}
		if(!$node)
		{
			return array();
		}
		if($node->nodeType == XML_ELEMENT_NODE)
		{
			$child_nodes = $node->childNodes;
			if($child_nodes->length == 1 and ($child_nodes->item(0)->nodeType == XML_TEXT_NODE or $child_nodes->item(0)->nodeType == XML_CDATA_SECTION_NODE))
			{
				$value = $child_nodes->item(0)->nodeValue;
					
				{
					if($value == "true"){
						return true;
					}else {
						if($value == "false"){
							return false;
						}else {
							return $value;
						}
					}

				}

			}
			elseif($child_nodes->length == 0)
			{
				return '';
			}
			else
			{
				$results = array();
				if($child_nodes->length>1 and $child_nodes->item(0)->nodeName == $child_nodes->item(1)->nodeName)
				{
					for ($i = 0; $i < $child_nodes->length; $i++)
					{
						$results[$i] = $this->decode($child_nodes->item($i));
					}
				}
				else
				{
					for ($i = 0; $i < $child_nodes->length; $i++)
					{
						$results[$child_nodes->item($i)->nodeName] = $this->decode($child_nodes->item($i));
						if($child_nodes->item($i)->nodeName=='options'){
							 foreach ($child_nodes->item($i)->attributes as $attr) 
						        { 
						            $results['options_'.$attr->nodeName] = $attr->nodeValue; 
						        } 
						}
					}
				}
				return $results;
			}
		}

	}

	/**
	 * Chuyển một array thành file XML
	 *
	 * @param array $arr
	 * @param string $filename
	 */
	 // Khoanb Edit 15.08.09
	function array2XML($arr = array(),$filename = ''){

		$doc = new DOMDocument('1.0','utf-8');
		$doc->formatOutput = true;
		if(!empty($arr)){
			foreach($arr as $key=>$value )
			{
				$this->createNodes($doc,$key,$value);
			}
			if(!empty($file)) $doc->save($filename);
			else $doc->saveXML();
		}else {
			return ;
		}
	}
	/**
	 * Chuyển tử mảng thành chuỗi dạng XML
	 *
	 * @param array $a
	 * @param integer $level
	 * @param string $suggest_name
	 * @return string
	 */
	static function array2XMLstring($a, $level = 0, $suggest_name = '', $aDefineData = array('label', 'description', 'order')) {
		if(is_array($a)) {
			$st = '';
			foreach($a as $key=>$value) {
				$next_suggest_name = '';
				if(is_int($key)) {
					$key = $suggest_name;
				} else {
					if($key[strlen($key)-1] == 's') {
						$next_suggest_name = substr($key, 0, strlen($key)-1);
					}
				}
				if(in_array($key, $aDefineData)){
					$value = "<![CDATA[{$value}]]>";
				}
				$st .= "\n".($level?str_repeat('	', $level):'').'<'.$key.'>'.
					CXml::array2XMLstring($value, $level+1, $next_suggest_name, $aDefineData).
					((is_array($value) and $level)?"\n".str_repeat('	', $level):'').'</'.$key.'>';
			}
			return $st;
		}
		else
		{
			return $a;
		}
	}
	/**
	 * Chuyển từ chuỗi XML thành máng
	 *
	 * @param string $xml_string
	 * @return array
	 */
	static function xmlstring2array($xml_string)
	{
		$xml = CXml();
		$xml->doc->loadXML($xml_string);
		return $xml->decode();
	}
}
function CXml($root = false)
{
	return new CXml($root);
}
?>